package py.una.pol.ii.is2.facade.registro;

/**
 * Clase que implementa la interfaz RegistroKilometrajeFacade
 * @author mbenitez
 * @date 05/05/2009
 */
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import py.una.pol.ii.is2.dao.flota.DetallePlantillaMantenimientoDAO;
import py.una.pol.ii.is2.dao.flota.VehiculoDAO;
import py.una.pol.ii.is2.dao.flota.VehiculoPlantillaDAO;
import py.una.pol.ii.is2.dao.registro.ChoferDAO;
import py.una.pol.ii.is2.dao.registro.RegistroUtilizacionDAO;
import py.una.pol.ii.is2.dao.taller.DetalleOrdenMantenimientoInsumoDAOLocal;
import py.una.pol.ii.is2.dao.taller.DetalleOrdenMantenimientoPlantillaDAOLocal;
import py.una.pol.ii.is2.dao.taller.OrdenMantenimientoDAOLocal;
import py.una.pol.ii.is2.domain.flota.PlantillaMantenimiento;
import py.una.pol.ii.is2.domain.flota.Vehiculo;
import py.una.pol.ii.is2.domain.flota.VehiculoPlantilla;
import py.una.pol.ii.is2.domain.registro.Chofer;
import py.una.pol.ii.is2.domain.registro.RegistroUtilizacion;
import py.una.pol.ii.is2.domain.sistema.Usuario;
import py.una.pol.ii.is2.domain.taller.DetalleOrdenMantenimientoPlantilla;
import py.una.pol.ii.is2.domain.taller.OrdenMantenimiento;
import py.una.pol.ii.is2.domain.taller.DetalleOrdenMantenimientoInsumo;
import py.una.pol.ii.is2.domain.flota.DetallePlantillaMantenimiento;
@Stateless(mappedName="registroFacade")
public class RegistroKilometrajeFacadeBean implements RegistroKilometrajeFacadeLocal, RegistroKilometrajeFacadeRemote {

    /**
     * Manejador de instancias de entidades para recuperar instancias desde
     * el Persistence Context
     */
    @PersistenceContext
    private EntityManager em;
    @EJB
    private VehiculoDAO vehiculoDao;
    private Vehiculo vehiculo;
    @EJB
    private ChoferDAO choferDao;
    private Chofer chofer;
    @EJB
    private RegistroUtilizacionDAO registroUtilizacionDao;
    private RegistroUtilizacion registroUtilizacion;
    @EJB
    private VehiculoPlantillaDAO vehiculoPlantillaDao;
    @EJB
    private OrdenMantenimientoDAOLocal ordenMantenimientoDao;
    private OrdenMantenimiento ordenMantenimiento;
    private Usuario usuario;
    @EJB
    DetalleOrdenMantenimientoPlantillaDAOLocal detalleOrdenDAO;
    @EJB
    DetalleOrdenMantenimientoInsumoDAOLocal detalleOrdenInsumoDAO;
    @EJB
    DetallePlantillaMantenimientoDAO detallePlantillaMantenimiento;
    /**
     * Inserta una entidad de RegistroKilometraje en la base de datos. 
     *
     * @param nroChapa Número de chapa del vehiculo
     * @param codChofer Código del chofer
     * @param descripcion Descripción de la operación
     * @param fecha Fecha de registro
     * @param inOut Indicador de entrada o salida de vehículo del establecimiento
     * @param kilometraje Índice del kilometraje actual para el vehículo en cuestión
     * @return true para señalar que la operación se ejecutó con éxito, en otro caso false.
     * @throws java.lang.Exception
     */
    public boolean insert(String nroChapa, Integer codChofer, String descripcion, Date fecha, Character inOut, Long kilometraje, Usuario usuario) throws Exception {
        boolean retorno = false;
        try {

            this.usuario = usuario;
            // verificamos el kilometraje del vehiculo
            vehiculo = vehiculoDao.findByNroChapa(nroChapa);
            chofer = choferDao.find(codChofer);
            if (kilometraje > vehiculo.getVehiKilometraje()) {
                registroUtilizacion = new RegistroUtilizacion();
                registroUtilizacion.setReutCodChofer(chofer);
                registroUtilizacion.setReutCodVehiculo(vehiculo);
                registroUtilizacion.setReutDescripcion(descripcion);
                registroUtilizacion.setReutFecha(fecha);
                registroUtilizacion.setReutInOut(inOut);
                registroUtilizacionDao.insert(registroUtilizacion);
                
                    // generacion automatica de ordenes
                verificarKilometrajes(kilometraje);
                // se actualiza el kilometraje
                updateKilometraje(kilometraje );
            
                
            }
            retorno = true;
            int ubicacion = 0;
            if(String.valueOf(inOut).equals("t"))
                ubicacion = 2;
            if(String.valueOf(inOut).equals("p"))
                ubicacion = 1;
            if(String.valueOf(inOut).equals("s"))
                ubicacion = 0;
            vehiculo.setVehiUbicacion(ubicacion);
            vehiculoDao.update(vehiculo);
        } catch (Exception e) {
            retorno = false;
            e.printStackTrace();
            throw e;
        } finally {
            return retorno;
        }
    }

    /**
     * Busca un registro de la tabla RegistroUtilizacion por el código de la misma.
     * Utiliza el NamedQuery <b>RegistroUtilizacion.findByReutCod</b> para su efecto.
     *
     * @param codObjeto Código del RegistroUtilizacion a buscar
     * @return retorno RegistroUtilizacion encontrado, en otro caso null.
     * @throws java.lang.Exception
     */
    public RegistroUtilizacion find(Integer codObjeto) throws Exception {
        RegistroUtilizacion retorno = null;
        try {
            Query q = em.createNamedQuery("RegistroUtilizacion.findByReutCod");
            q.setParameter("reutCod", codObjeto);
            retorno = (RegistroUtilizacion) q.getSingleResult();
        } catch (Exception e) {
            throw e;
        } finally {
            return retorno;
        }
    }

    /**
     * Devuelve una lista completa de RegistroUtilizacion en caso de que el parámetro condicion
     * sea o bien <b>null</b> o <b>vacio</b>, y aquellas que coincidan con la condicion
     * comenzando con la palabra clave <b>where</b>.
     * Las entidades son devueltas ordenadas por la clave primaria.
     *
     * @param condicion Restricción para la selección de resultados
     * @return retorno Lista de resultados arrojados por la ejecución de la consulta, en otro caso null.
     * @throws java.lang.Exception
     */
    public List<RegistroUtilizacion> getListaRegistroKilometrajes(String condicion) throws Exception {
        List<RegistroUtilizacion> retorno = null;
        Query q = null;
        try {
            if (condicion == null || condicion.length() == 0) {
                q = em.createNamedQuery("RegistroUtilizacion.findAll");
            } else {
                q = em.createQuery("select reut from RegistroUtilizacion reut " + condicion + " order by reut.reutCod");
            }
            // recuperamos la lista
            retorno = q.getResultList();
        } catch (Exception e) {
            throw e;
        } finally {
            return retorno;
        }
    }

    /**
     * Itera sobre las plantillas asignadas a un vehiculo y actualiza los
     * kilometrajes faltantes de las mismas. En caso que el kilometraje se cumpla
     * se inicializa el contador.
     *
     * @param insertedKilometraje
     * @throws java.lang.Exception
     */
    private void verificarKilometrajes(Long insertedKilometraje) throws Exception {
        Long kilometraje = insertedKilometraje - vehiculo.getVehiKilometraje();
        Long kilometrajeRestante;
        PlantillaMantenimiento plantilla;
        // iteramos sobre las plantillas asignadas al vehiculo
        for (VehiculoPlantilla vehiculoPlantilla : vehiculo.getVehiculoPlantillaCollection()) {
            plantilla = vehiculoPlantilla.getPlantillaMantenimiento();


            kilometrajeRestante = vehiculoPlantilla.getVeplKilometrajeFaltante().longValue() - kilometraje;
            
            
            // comprobamos que el km se haya cumplido
            if (kilometrajeRestante <= 0) {
                // se reinicia el kilometraje regresivo
                vehiculoPlantilla.setVeplKilometrajeFaltante(plantilla.getPlmaKilometraje());
                vehiculoPlantillaDao.update(vehiculoPlantilla);
                agregarPlantilla(plantilla);
            } else {
                // se decrementa el kilometraje faltante para la plantilla
                vehiculoPlantilla.setVeplKilometrajeFaltante(kilometrajeRestante);
                vehiculoPlantillaDao.update(vehiculoPlantilla);
            }
        }
    }

    /**
     * Verifica que para una plantilla con kilometraje cumplido, exista una
     * orden de mantenimiento. De no existir la orden, la crea, asignando la
     * plantilla como detalle de la misma.
     *
     * @param plantilla
     * @throws java.lang.Exception
     */
    private void agregarPlantilla(PlantillaMantenimiento plantilla) throws Exception {
        // inicializamos el detalle que vamos a agregrgar

        
        // verificamos la existencia de la orden
        ordenMantenimiento = ordenMantenimientoDao.findByPendiente(vehiculo);
        if (ordenMantenimiento == null) {
            // creamos una nueva orden
            ordenMantenimiento = new OrdenMantenimiento();
            ordenMantenimiento.setOrmaFecha(registroUtilizacion.getReutFecha());
            ordenMantenimiento.setOrmaCodVehiculo(vehiculo);
            ordenMantenimiento.setOrmaEstado(OrdenMantenimiento.estadoPendiente);
            ordenMantenimiento.setOrmaCodUsuario(usuario);
            ordenMantenimiento.setOrmaCostoTotal(plantilla.getPlmaCostoInsumos().add(plantilla.getPlmaCostoManoObra()));
            ordenMantenimientoDao.insert(ordenMantenimiento);
           
        }
            List<DetalleOrdenMantenimientoPlantilla> lista = detalleOrdenDAO.getListaDetalleOrdenMantenimientoPlantillasByCodOrden(ordenMantenimiento);
            DetalleOrdenMantenimientoPlantilla detallePlantilla = new DetalleOrdenMantenimientoPlantilla();
            boolean existePlantilla = false;
            Integer deopCod;
                if (!lista.isEmpty()){
                    Iterator<DetalleOrdenMantenimientoPlantilla> i = lista.iterator();
                    while(i.hasNext()){
                        DetalleOrdenMantenimientoPlantilla det = i.next();
                        if (det.getDeopPlantilla().getPlmaCod() == plantilla.getPlmaCod()){
                            existePlantilla = true;
                            detallePlantilla.setDeopCod(det.getDeopCod());
                            break;
                        }

                    }
                }
                detallePlantilla.setDeopPlantilla(plantilla);
                detallePlantilla.setDeopEstado(0);
                detallePlantilla.setDeopCostoManoObra(plantilla.getPlmaCostoManoObra());
                detallePlantilla.setDeopCostoInsumos(plantilla.getPlmaCostoInsumos());
                detallePlantilla.setDeopCodOrden(ordenMantenimiento);
                if(existePlantilla){
                    detalleOrdenDAO.update(detallePlantilla);
                }else{
                    detalleOrdenDAO.insert(detallePlantilla);
                    agregarInsumo(detallePlantilla);
                }
                ordenMantenimientoDao.update(ordenMantenimiento);
    }

    /**
     * Actualiza el kilometraje del vehiculo con la diferencia entre el
     * ingresado por el operador y el almacenado en el registro del vehiculo.
     *
     * @param updateKilometraje
     * @throws java.lang.Exception
     */
    private void agregarInsumo(DetalleOrdenMantenimientoPlantilla detallePlantilla) throws Exception{
         System.out.println("Codigo de plantilla: " + detallePlantilla.getDeopPlantilla().getPlmaCod());
         List<DetallePlantillaMantenimiento> Lista = detallePlantillaMantenimiento.getListaDetallePlantillaMantenimientosByCodPlantilla(detallePlantilla.getDeopPlantilla());
         if (Lista == null){
            System.out.println("vacio");
         }else{
             Iterator<DetallePlantillaMantenimiento> it = Lista.iterator();
             while(it.hasNext()){
                py.una.pol.ii.is2.domain.flota.DetallePlantillaMantenimiento detallePlantillaMantenimiento = it.next();
                DetalleOrdenMantenimientoInsumo detalleOrdenInsumo = new DetalleOrdenMantenimientoInsumo();
                detalleOrdenInsumo.setDeoiCodInsumo(detallePlantillaMantenimiento.getDepmCodInsumo());
                detalleOrdenInsumo.setDeoiCantidad(detallePlantillaMantenimiento.getDepmCantidad());
                detalleOrdenInsumo.setDeoiDescripcionUtilizacion("Mantenimiento Preventivo");
                detalleOrdenInsumo.setDeoiDetalleOrden(detallePlantilla);
                detalleOrdenInsumo.setDeoiPrecio(detallePlantillaMantenimiento.getDepmCodInsumo().getInsuPrecio());
                detalleOrdenInsumoDAO.insert(detalleOrdenInsumo);
             }
         }

    }

    private void updateKilometraje(Long updateKilometraje) throws Exception {
        Long kilomentraje = updateKilometraje ;//- vehiculo.getVehiKilometraje();
        vehiculo.setVehiKilometraje(kilomentraje);
        vehiculoDao.update(vehiculo);
    }

}
